import Snake from "./Snake";
import SVGGraphics from "../class/SVGGraphics";
import TWEEM from "../class/Tween";
import {
    VIEW_WIDTH,
    VIEW_HEIGHT,
    VIEW_CENTER,
    L_ANI_TIME,
    B_ANI_TIME,
    M_ANI_TIME,
    S_ANI_TIME,
    on,
    square,
    stageManager,
    renderer,
    LineAnimate,
} from "./common";

interface Point {
    x: number,
    y: number
}
export interface FoodEffectConfig {
    /**增长体积 */
    add_body?: number,
    /**增长速度 */
    add_speed?: number,
    /**增长灵敏度 */
    add_sensitivity?: number
}

export class FoodEffect {
    add_body = 0
    add_speed = 0
    add_sensitivity = 0

    constructor(config?: FoodEffectConfig) {
        config && this.importConfig(config);
    }
    importConfig(config: FoodEffectConfig) {
        this.add_body = config.add_body
        this.add_speed = config.add_speed
        this.add_sensitivity = config.add_sensitivity
    }
}

export default class Food extends PIXI.Sprite {
    name: string = "无用食物"
    private _ANI = new TWEEM
    /**是否无视碰撞检测：在被吃后，物体动画中，这时候无需有任何作用，只需要把动画跑完就行了 */
    is_ignore: boolean = false
    effect = new FoodEffect
    constructor(tex?: PIXI.Texture) {
        super(tex)
        var self = this;
        this.on("eated", () => {
            this.is_ignore = true;
            // this._ANI.Tween("fade out", { alpha: 1, scale: 1 }, true)
            //     .to({
            //         alpha: 0,
            //         scale: 0
            //     }, L_ANI_TIME)
            //     .easing(TWEEM.Easing.Quartic.In)
            //     .onUpdate(function () {
            //         self.alpha = this.alpha
            //         self.scale = this.scale
            //     })
            //     .onComplete(() => {
            //         this.parent.removeChild(this)
            //         this.destroy();
            //     })
            //     .start()

            this.parent.removeChild(this)
            this.destroy();
        });
    }
    onEat(snake: Snake) {
        this.emit("eated");
        this.effectFood(snake);
    }
    /**触发食物功效 */
    effectFood(snake) {
        var food_effect = this.effect
        if (food_effect.add_body) {
            snake.addBody(food_effect.add_body)
        }
        if (food_effect.add_speed) {
            snake.addSpeed(food_effect.add_speed)
        }
        if (food_effect.add_sensitivity) {
            snake.addSensitivity(food_effect.add_sensitivity)
        }
    }
    update(time?: number) {
        this._ANI.update(time)
    }
    destroy() {
        PIXI.Container.prototype.destroy.call(this);
        this._ANI = null;
    }
}
export var FOOD_CONTAINER_UNIT_SIZE = 600;

const Emitter = PIXI.particles.Emitter;
export interface EatAbleFood {
    x: number,
    y: number,
    effect: FoodEffect
};

export class FoodContainer extends PIXI.Container {
    private _ANI = new TWEEM
    constructor() {
        super();
    }
    addFood(food: Food, x: number, y: number) {
        food.x = x;
        food.y = y;
        this.addChild(food)
    }
    getCollisionItemWithCircle(x: number, y: number, r: number = 0, filter: (item: PIXI.DisplayObject | PIXI.Point | { x: number, y: number }, x: number, y: number, index: number) => boolean) {
        var children_indexs = [];
        // this.children.forEach((item: PIXI.DisplayObject, index) => {
        //     if (item instanceof Food || item instanceof Emitter) {
        //         if (filter(item, x, y, index)) {
        //             children_indexs.push(index)
        //         }
        //     }
        // })
        var emiter_pos_indexs = [];
        this._particle_foods.forEach((item, index) => {
            if (filter(item, x, y, index)) {
                emiter_pos_indexs.push(index)
            }
        })
        var res: {
            children_indexs: number[],
            emiter_pos_indexs: number[]
        } = {
                children_indexs: children_indexs,
                emiter_pos_indexs: emiter_pos_indexs
            };
        return res;
    }
    private _elapsed;
    /**上一次渲染light的index集合 */
    private _pre_ligth_render_map = {};
    update(time?: number) {
        this._ANI.update();

        var children = this.children;
        for (var food of children) {
            if (food instanceof Food) {
                (<Food>food).update(time)
            } else if (food instanceof PIXI.particles.Emitter) {
            }
        }

        var _now = Date.now();
        var _elapsed = this._elapsed || (_now - 16);
        var delay_time = (_now - _elapsed) * 0.001
        this._elapsed = _now;
        // var emitter = this._emitter;
        // if (emitter && this._particle_foods.length) {
        //     emitter.update(delay_time);
        // }

        var _pre_ligth_render_map = this._pre_ligth_render_map;
        var lights = this._lights;
        var _emitters = this._emitters
        var _lightsContainer = this._lightsContainer;
        if (_emitters && _emitters.length) {
            _emitters.forEach((emitter, i) => {
                if (emitter.ownerPos.x >= this.show_emitter_range_left && emitter.ownerPos.x <= this.show_emitter_range_right &&
                    emitter.ownerPos.y >= this.show_emitter_range_top && emitter.ownerPos.y <= this.show_emitter_range_bottom) {
                    emitter.update(delay_time)
                    if (!_pre_ligth_render_map[i]) {
                        _pre_ligth_render_map[i] = true;
                        _lightsContainer.addChild(lights[i])
                    }
                } else {
                    if (_pre_ligth_render_map[i]) {
                        _pre_ligth_render_map[i] = false
                        _lightsContainer.removeChild(lights[i])
                    }
                }
            })
        }
        var death_emitters = this._death_emitters;
        if (death_emitters && death_emitters.length) {
            death_emitters.forEach(emitter => {
                emitter.update(delay_time)
                return emitter.emit
            })
        }
    }

    _particle_foods: (EatAbleFood)[] = []
    private _show_particle_foods: (EatAbleFood)[] = []
    private _emitters: PIXI.particles.Emitter[] = []
    private _lights: PIXI.lights.Light[] = [];
    private _lightsContainer = (() => {
        var con = new PIXI.Container();
        this.addChild(con);
        return con;
    })()
    addParticleFood(effect: FoodEffect, x, y) {

        const add_body = effect.add_body;
        const add_speed = effect.add_speed;
        const add_sensitivity = effect.add_sensitivity;
        const add_total = add_body + add_speed + add_sensitivity;
        if (!add_total) {
            return
        }
        var random_color = add_total.toFixed(9).match(/\d\d\d/g);

        var endScale = (add_body / 10 + add_speed / 20 + add_sensitivity / 50);
        var startScale = endScale * 1.2 + 0.3;

        var darkColor = [
            parseInt(random_color[0]) / 999 * 127.5 + 127.5,
            parseInt(random_color[1]) / 999 * 100 + 155,
            parseInt(random_color[2]) / 999 * 55 + 200,
        ];
        var lightColor = [
            darkColor[0] * 0.8,
            darkColor[1] * 0.8,
            darkColor[2] * 0.8,
        ]
        var number_color = darkColor[0] * 0x10000 + darkColor[1] * 0x100 + darkColor[2]
        // var light_wrap = new PIXI.Container();
        var light = new PIXI.Sprite(FoodTexture);
        light.anchor.set(0.5, 0.5);
        light.scale.set(startScale * 5, startScale * 5);
        light.alpha = endScale;
        light.tint = number_color;
        light.blendMode = PIXI.BLEND_MODES.ADD;
        light.x = x;
        light.y = y;
        // light_wrap.addChild(light);

        var emitter = new Emitter(this, '/images/food_particle.png', {
            "alpha": {
                "start": 1,
                "end": 1
            },
            "scale": {
                "start": startScale * 0.2,
                "end": startScale * 0.2,
                "minimumScaleMultiplier": 0
            },
            "color": {
                "start": "54d7ff",
                "end": "50eeff"
                // "end": "2b00ff"
            },
            "speed": {
                "start": 10 * startScale,
                "end": 0
            },
            "acceleration": {
                "x": 0,
                "y": 0
            },
            "startRotation": {
                "min": 0,
                "max": 360
            },
            "noRotation": false,
            "rotationSpeed": {
                "min": 0,
                "max": 0
            },
            "lifetime": {
                "min": 0.5,
                "max": 1
            },
            "blendMode": "add",
            "frequency": 0.01,
            "emitterLifetime": -1,
            "maxParticles": 1,
            "pos": {
                "x": 0,
                "y": 0
            },
            "addAtBack": false,
            "spawnType": "point",
        });
        emitter.startColor = darkColor;
        emitter.endColor = lightColor;
        emitter.emit = true;
        emitter.resetPositionTracking();
        emitter.updateOwnerPos(x, y);

        this._particle_foods.push({ x, y, effect });
        this._emitters.push(emitter);
        this._lights.push(light);
    }
    // removeParticleFoodAt(index: number) {
    //     return this._particle_foods.splice(index, 1)[0]
    // }
    /**已经移除的emitter，这里在执行最后的消失动画 */
    private _death_emitters: PIXI.particles.Emitter[] = [];
    private _death_lights: PIXI.Container[] = [];
    removeParticleFoodAt(index: number, options: {
        fly_to?: Point
    } = {}) {
        var death_emitters = this._death_emitters;
        var death_emitter = this._emitters.splice(index, 1)[0];
        const die_time = 300;
        function remove_deatch_emitter() {
            // var index = death_emitters.indexOf(death_emitter);
            // if (index > -1) {
            //     death_emitters.splice(index, 1);
            //     death_emitter.destroy();
            // }
        }
        var fly_to = options.fly_to;
        if (fly_to && isFinite(fly_to.x) && isFinite(fly_to.y)) {
            var ownerPos_x = death_emitter.ownerPos.x
            var ownerPos_y = death_emitter.ownerPos.y
            this._ANI.Tween({ v: 0 })
                .to({
                    v: 1
                }, die_time)
                .easing(TWEEM.Easing.Quartic.In)
                .onComplete(remove_deatch_emitter)
                .onUpdate(function () {
                    /**
                     * 动态获取，是的fly_to对象可以被外部动态修改或者使用getter属性动态获取
                     */
                    var fly_to = options.fly_to;
                    var res_point = LineAnimate([death_emitter.spawnPos], [{ x: fly_to.x - ownerPos_x, y: fly_to.y - ownerPos_y }], this.v)[0];
                    death_emitter.updateSpawnPos(res_point.x, res_point.y);
                })
                .start()
        } else {
            setTimeout(remove_deatch_emitter, die_time)
        }

        death_emitter.cleanup();
        death_emitter.endScale = 0;
        death_emitter.emitterLifetime = 0.001 * die_time;
        const fps = 10;
        death_emitter.startAlpha = 2 / fps;
        death_emitter.endAlpha = 2 / fps;
        death_emitter.maxParticles = fps;
        death_emitter.frequency = 1 / fps / death_emitter.maxParticles;
        death_emitter.minLifetime = 1 / fps;
        death_emitter.maxLifetime = 1 / fps;
        death_emitter.emit = true;
        death_emitters.push(death_emitter);
        var light = this._lights.splice(index, 1)[0];
        var remover_light = this._lightsContainer.removeChild(light);
        var _pre_ligth_render_map = this._pre_ligth_render_map;
        for (var i in _pre_ligth_render_map) {
            var _i = ~~i;
            if (_i > index) {
                _pre_ligth_render_map[_i - 1] = _pre_ligth_render_map[i];
                _pre_ligth_render_map[i] = false;
            }
        }
        // console.log(death_emitter.ownerPos, light.position, remover_light)
        return this._particle_foods.splice(index, 1)[0]
    }
    /**移除某个点上的食物*/
    removeParticleFood(x, y) {
        this._particle_foods.some((food, index) => {
            if (food.x == x && food.y == y) {
                this.removeParticleFoodAt(index);
                return true
            }
        });
    }
    clearParticleFood() {
        console.log("CLEAR!!!")
        //销毁食物
        this._particle_foods = [];
        //销毁食物·粒子效果
        this._emitters.forEach(emitter => {
            emitter.destroy()
        })
        this._emitters = [];
        //销毁食物·灯光效果
        var _pre_ligth_render_map = this._pre_ligth_render_map;
        this._lights.forEach((light, i) => {
            if (_pre_ligth_render_map[i]) {
                this._lightsContainer.removeChild(light)
            }
        });
        this._lights = [];
        this._pre_ligth_render_map = {};
    }

    eatFood(food: PIXI.DisplayObject | PIXI.Point | { x: number, y: number }) {
        if (food instanceof Food) {

        }
    }
    // updatePos(x: number, y: number, overflow: number = 10) {
    //     this.x = x;
    //     this.y = y;
    //     var emitter = this._emitter
    //     var spawnRect = emitter.spawnRect;
    //     var width = spawnRect.width + overflow
    //     var height = spawnRect.height + overflow
    //     this._show_particle_foods = this._particle_foods.filter((item) => {
    //         var _x = item.x + x
    //         var _y = item.y + y
    //         return _x > -overflow && _x < width && _y > -overflow && _y < height
    //     });
    // }
    private show_emitter_range_left = 0;
    private show_emitter_range_right = 0;
    private show_emitter_range_top = 0;
    private show_emitter_range_bottom = 0;
    updatePos(x: number, y: number, overflow: number = 10) {
        this.x = x;
        this.y = y;
        this.show_emitter_range_left = -x - overflow
        this.show_emitter_range_right = this.show_emitter_range_left + VIEW_WIDTH + overflow + overflow
        this.show_emitter_range_top = -y - overflow
        this.show_emitter_range_bottom = this.show_emitter_range_top + VIEW_HEIGHT + overflow + overflow
    }
}

export var BodyFoodTexture = PIXI.Texture.fromImage("/images/food_particle.png");
const FoodTexture = PIXI.Texture.fromImage("./js/lib/pixi.js-3.0.11/particle.png");
export class BodyFood extends Food {
    name: string = "肉"
    constructor() {
        super(BodyFoodTexture)
        this.width = 10;
        this.height = 10;
        // var view = SVGGraphics.importFromSVG(`<circle cx="0" cy="0" r="5" stroke="#FFF"  stroke-width="1" fill="yellow" />`)._graphics
        // view.cacheAsBitmap = true;
        // this.addChild(view);
        this.effect.add_body = 1;
    }
}

export class SpeedFood extends Food {
    name: string = "速度"
    constructor() {
        super()
        var view = SVGGraphics.importFromSVG(`<circle cx="0" cy="0" r="5" stroke="#FFF"  stroke-width="1" fill="blue" />`)._graphics
        view.cacheAsBitmap = true;
        this.addChild(view);
        this.effect.add_speed = 2;
    }
}
/**增加灵敏度的食物 */
export class SensitivityFood extends Food {
    name: string = "灵敏"
    constructor() {
        super()
        var view = SVGGraphics.importFromSVG(`<circle cx="0" cy="0" r="5" stroke="#FFF"  stroke-width="1" fill="green" />`)._graphics
        view.cacheAsBitmap = true;
        this.addChild(view);
        this.effect.add_sensitivity = 5;
    }
}